home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d20 / msgq160s.arc / EDITMAIL.C < prev    next >
C/C++ Source or Header  |  1991-10-26  |  26KB  |  1,312 lines

  1. /*
  2.  * EDITMAIL.C - Message editing
  3.  *
  4.  * Msged/Q message editor for QuickBBS  Copyright 1990 by P.J. Muller
  5.  *
  6.  */
  7.  
  8. #include <stdlib.h>
  9. #include <ctype.h>
  10. #include <string.h>
  11.  
  12. #include "msged.h"
  13. #include "screen.h"
  14. #define EDITMAIL
  15. #include "editmail.h"
  16. #include "shell.h"
  17.  
  18. #include <assert.h>        /* special */
  19.  
  20. void    putl(LINE *l);
  21.  
  22. #define clearline(l,c)    memset(l,0,c)
  23. #define BUFLEN 256
  24.  
  25. static    int    down1(int y);
  26. static    int    wrap(LINE *cl,char *r,int y);
  27. static    void    reformat(LINE *cl);
  28. static    void    insert_char(char c);
  29. static    void    wrapline(void);
  30.  
  31. static int done = FALSE;
  32. static int insert = ON;
  33. static int x = 1, y = 1;
  34.  
  35. static char line[BUFLEN];
  36. static LINE *current = NULL;
  37. static LINE *first = NULL;
  38. static LINE *last = NULL;
  39. static LINE *pastebuf = NULL;
  40. static int changed = 0;
  41. static int direction = 0;
  42. static int noteflag;
  43.  
  44. LINE *anchorpt = NULL;
  45. extern LINE *top;
  46. extern LINE *bottom;
  47.  
  48. int editmsg(void);
  49.  
  50. void putl(LINE *l)
  51. {
  52.     if (l->block)
  53.         set_color(co_block);
  54.     else if (l->hide)
  55.         set_color(co_info);
  56.     else if (l->quote)
  57.         set_color(co_quote);
  58.     else
  59.         set_color(co_normal);
  60.  
  61. #ifdef ZAPTHISOUT
  62.     { char *s;
  63.       for (s=l->text;  *s != EOS;  s++)
  64.         if (*s == ' ') bputc(250); else bputc(*s);
  65.     }
  66. #else
  67.     bputs(l->text);
  68. #endif
  69.  
  70.     if (techie && (strchr(l->text,'\n') != NULL)) {
  71.       set_color(co_info);
  72.       bputc((char)20);    /* paragraph mark */
  73.     } /* if */
  74.  
  75.     set_color(co_normal);
  76. }
  77.  
  78. int dorot13(int c)
  79.  
  80. {
  81.     switch (rot13) {
  82.         case 1:
  83.             c &= 0x7F;
  84.             if (!isalpha(c))
  85.                 return(c);
  86.                 if (((c >= 'A') && (c <= 'M')) || ((c >= 'a') && (c <= 'm')))
  87.                     return(c + 0xd);
  88.             if (((c >= 'N') && (c <= 'Z')) || ((c >= 'n') && (c <= 'z')))
  89.                     return(c - 0xd);
  90.                 break;
  91.                 
  92.             case 2:
  93.             return (c >= '!') ? (((c + 47) > '~') ? (c - 47) : (c + 47)) : c;
  94.  
  95.         case 3:
  96.             return tolower(c);
  97.     }
  98.     return(c);
  99. }
  100.  
  101. void    go_bol()
  102.  
  103. {
  104.     x = 1;
  105. }
  106.  
  107. static int down1(int y)
  108. {
  109.         if (++y > (maxy - 6)) {
  110.                 y = maxy - 6;
  111.                 scrollup(1, 7, maxx, maxy, 1);
  112.     }
  113.     gotoxy(1, y + 6);
  114.     return (y);
  115. }
  116.  
  117. static int wrap(LINE *cl,char *r,int y)
  118.  
  119. {
  120.         char *l = NULL;
  121.         char *s = NULL;
  122.         LINE *nl = NULL;
  123.         int i = 0;
  124.         int j = 0;
  125.         int x2 = 0;
  126.  
  127.         if (cl == NULL)
  128.                 return(x);
  129.  
  130.         if (r != NULL)
  131.                 j = i = strlen(r);
  132.  
  133.         if (cl->text != NULL)
  134.                 i += strlen(cl->text);
  135.  
  136.         if (i != 0)
  137.                 l = (char *) calloc(1,i+5);
  138.  
  139.         if (r != NULL) {
  140.                 strcpy(l,r);
  141.                 ptrfree(r);
  142.         }
  143.  
  144.         if (cl->text != NULL) {
  145.                 strcat(l,cl->text);
  146.                 ptrfree(cl->text);
  147.                 cl->text = NULL;
  148.         }
  149.  
  150.         x2 = strlen(l);
  151.  
  152.         if (x2 < rm) {
  153.                 cl->text = l;
  154.         if ((y + 6) <= maxy) {
  155.                         gotoxy(1,y + 6);
  156.             clreol();
  157.             putl(cl);
  158.                 }
  159.                 return(x);
  160.         }
  161.  
  162.         s = l + rm;
  163.  
  164.         while (isspace(*s))
  165.                 s--;
  166.  
  167.         while (!isspace(*s) && (s > l))
  168.                 s--;
  169.  
  170.         if (s <= l) {
  171.                 s = l + rm;
  172.                 while (!ispunct(*s) && (s > l))
  173.                         s--;
  174.         }
  175.  
  176.         if (s <= l)
  177.                 s = l + rm - 1;
  178.         else
  179.                 s++;
  180.  
  181.         r = strdup(s);
  182.         assert(r);
  183.  
  184.         *s = '\0';
  185.  
  186.         if ((x + l) > (s - j))
  187.         x2 = (x + j) - (int)(s - l);
  188.         else
  189.                 x2 = x;
  190.  
  191.         cl->text = (char *) realloc(l,strlen(l)+1);
  192.         if ((y + 6) <= maxy) {
  193.                 gotoxy(1,y + 6);
  194.                 clreol();
  195.         putl(cl);
  196.                 y++;
  197.         }
  198.  
  199.         if (strchr(r,'\n') != NULL) {
  200.                 if ((y+6) <= maxy) {
  201.                         if ((y+6) < maxy)
  202.                                 scrolldown(1,y+6,maxx,maxy,1);
  203.                         gotoxy(1,y+6);
  204.                         clreol();
  205.                         bputs(r);
  206.                 }
  207.                 nl = (LINE *) calloc(1,sizeof(LINE));
  208.                 assert(nl);
  209.                 nl->next = cl->next;
  210.                 if (cl->next != NULL)
  211.                         cl->next->prev = nl;
  212.                 else
  213.                         last = nl;
  214.                 nl->prev = cl;
  215.                 cl->next = nl;
  216.                 nl->text = r;
  217.                 return(x2);
  218.         }
  219.  
  220.         if (cl->next == NULL) {
  221.                 cl->next = (LINE *) calloc(1,sizeof(LINE));
  222.                 assert(cl->next);
  223.                 cl->next->prev = cl;
  224.                 cl->next->text = NULL;
  225.                 last = cl->next;
  226.         }
  227.  
  228.         assert(cl->next);
  229.     wrap(cl->next,r,y);
  230.         return(x2);
  231. }
  232.  
  233. void    insert_char(char c)
  234. {
  235.     strins(line, c, x);
  236.     if (strlen(line) > rm) {
  237.         wrapline();
  238.         return;
  239.     }
  240.     gotoxy(x, y + 6);
  241.         clreol();
  242.     assert(line + x - 1);
  243.     if (current->block)
  244.         set_color(co_block);
  245.     else if (current->hide)
  246.         set_color(co_warn);
  247.     else if (current->quote)
  248.         set_color(co_quote);
  249.     else
  250.         set_color(co_normal);
  251.     bputs((line + x - 1));
  252.     set_color(co_normal);
  253.     x++;
  254. }
  255.  
  256. void    delete_character()
  257.  
  258. {
  259.     LINE *l;
  260.         char *t,*s;
  261.  
  262.     if (current->text != NULL)
  263.         ptrfree(current->text);
  264.     current->text = strdup(line);
  265.     assert(current->text);
  266.     changed = TRUE;
  267.  
  268.         if ((*(line + x) == '\0') && (current->next != NULL)) {
  269.                 t = current->text;
  270.                 s = strchr(t,'\n');
  271.                 if (s != NULL)
  272.                         *s = '\0';
  273.         current->text = current->next->text;
  274.         l = current->next;
  275.                 if (current->next->next != NULL)
  276.                         current->next->next->prev = current;
  277.                 current->next = current->next->next;
  278.         ptrfree(l);
  279.                 if ((y+6) < maxy)
  280.                         scrollup(1,(y+6),maxx,maxy,1);
  281.         wrap(current,t,y);
  282.         clearline(line,BUFLEN);
  283.         if (current->text != NULL)
  284.             strcpy(line,current->text);
  285.                 return;
  286.         }
  287.  
  288.     strdel(line, x);
  289.  
  290.         clreol();
  291.         assert(line + x - 1);
  292.     if (current->block)
  293.         set_color(co_block);
  294.     else if (current->hide)
  295.         set_color(co_warn);
  296.     else if (current->quote)
  297.         set_color(co_quote);
  298.     else
  299.         set_color(co_normal);
  300.     bputs((line + x - 1));
  301. }
  302.  
  303. void    backspace()
  304. {
  305.     changed = TRUE;
  306.  
  307.     if (x == 1) {
  308.         go_up();
  309.         go_eol();
  310.         delete_character();
  311.         return;
  312.     }
  313.     strdel(line, --x);
  314.     gotoxy(x, y + 6);
  315.     clreol();
  316.     assert(line + x - 1);
  317.     if (current->block)
  318.         set_color(co_block);
  319.     else if (current->hide)
  320.         set_color(co_warn);
  321.     else if (current->quote)
  322.         set_color(co_quote);
  323.     else
  324.         set_color(co_normal);
  325.     bputs((line + x - 1));
  326. }
  327.  
  328. void    wrapline()
  329.  
  330. {
  331.         int x2;
  332.  
  333.         if (changed) {
  334.                 if (current->text != NULL)
  335.                         ptrfree(current->text);
  336.                 current->text = strdup(line);
  337.                 assert(current->text);
  338.                 changed = FALSE;
  339.         }
  340.  
  341.     x2 = wrap(current,NULL,y);
  342.         if (x2 != x) {
  343.                 current = current->next;
  344.                 x = x2;
  345.                 y = down1(y);
  346.                 gotoxy(1,y+6);
  347.                 clreol();
  348.         putl(current);
  349.     }
  350.     x++;
  351.     clearline(line,BUFLEN);
  352.     if (current->text != NULL)
  353.         strcpy(line,current->text);
  354. }
  355.  
  356. void    go_eol()
  357. {
  358.     x = strlen(line);
  359.  
  360.     if (*(line + x - 1) != '\n')
  361.         x++;
  362.  
  363.     x = max(1, x);
  364. }
  365.  
  366. void    go_up()
  367. {
  368.     if (current->prev == NULL)
  369.         return;
  370.  
  371.         if (changed) {
  372.                 if (current->text != NULL)
  373.                         ptrfree(current->text);
  374.  
  375.                 current->text = strdup(line);
  376.                 assert(current->text);
  377.                 changed = FALSE;
  378.     }
  379.  
  380.     if (y == 1)
  381.         scrolldown(1, y + 6, maxx, maxy, 1);
  382.     else
  383.         y--;
  384.  
  385.     current = current->prev;
  386.  
  387. #if 0
  388.     if ((current != anchorpt) && (anchorpt != NULL))
  389.         current->block ^= 1;
  390. #endif
  391.  
  392.         direction = UP;
  393.  
  394.     assert(current);
  395.  
  396.     clearline(line, BUFLEN);
  397.  
  398.     if (current->text != NULL)
  399.         strcpy(line, current->text);
  400.  
  401.     if (x > strlen(line))
  402.         go_eol();
  403.  
  404.     gotoxy(1, y + 6);
  405.     putl(current);
  406. }
  407.  
  408. void    go_down()
  409. {
  410.     if      (current->next == NULL)
  411.                 return;
  412.  
  413.         if (changed) {
  414.                 if (current->text != NULL)
  415.                         ptrfree(current->text);
  416.  
  417.                 current->text = strdup(line);
  418.                 assert(current->text);
  419.                 changed = FALSE;
  420.         }
  421.  
  422.         direction = DOWN;
  423.  
  424.     if (y > (maxy - 7))
  425.         scrollup(1, 7, maxx, maxy, 1);
  426.     else
  427.         y++;
  428.  
  429.     current = current->next;
  430.  
  431. #if 0
  432.     if ((current != anchorpt) && (anchorpt != NULL))
  433.         current->block ^= 1;
  434. #endif
  435.  
  436.     assert(current);
  437.  
  438.     clearline(line, BUFLEN);
  439.  
  440.     if (current->text != NULL)
  441.         strcpy(line, current->text);
  442.  
  443.     if (x > strlen(line))
  444.         go_eol();
  445.  
  446.     gotoxy(1, y + 6);
  447.     putl(current);
  448.     x = max(1, x);
  449. }
  450.  
  451. void    go_left()
  452. {
  453.     if (x == 1) {
  454.         if (current->prev != NULL) {
  455.                 go_up();
  456.             go_eol();
  457.         }
  458.         return;
  459.     }
  460.     x--;
  461. }
  462.  
  463. void    go_right()
  464. {
  465.     if (*(line + x - 1) == '\0') {
  466.         if (current->next != NULL) {
  467.             go_down();
  468.             x = 1;
  469.         }
  470.         return;
  471.     }
  472.  
  473.     if (*(line + x - 1) == '\n') {
  474.         if (current->next != NULL) {
  475.             go_down();
  476.             x = 1;
  477.         }
  478.         return;
  479.     }
  480.     x++;
  481. }
  482.  
  483. void    go_word_right()
  484. {
  485.     if (*(line + x - 1) == '\0') {
  486.         if (current->next != NULL) {
  487.             go_down();
  488.             x = 1;
  489.         }
  490.         return;
  491.     }
  492.  
  493.     if (*(line + x - 1) == '\n') {
  494.         if (current->next != NULL) {
  495.             go_down();
  496.             x = 1;
  497.         }
  498.         return;
  499.     }
  500.  
  501.     while (isspace(*(line + x - 1)) && (x <= strlen(line)))
  502.         x++;
  503.     while (!isspace(*(line + x - 1)) && (x <= strlen(line)))
  504.         x++;
  505.     while (isspace(*(line + x - 1)) && (x <= strlen(line)))
  506.         x++;
  507.  
  508.     if (*(line + x - 2) == '\n')
  509.         x--;
  510. }
  511.  
  512. void    go_word_left()
  513. {
  514.     if (x == 1) {
  515.         if (current->prev != NULL) {
  516.                 go_up();
  517.             go_eol();
  518.         }
  519.         return;
  520.     }
  521.  
  522.     while (isspace(*(line + x - 1)) && (x > 1))
  523.         x--;
  524.     while (!isspace(*(line + x - 1)) && (x > 1))
  525.         x--;
  526.     while (isspace(*(line + x - 1)) && (x > 1))
  527.         x--;
  528.     while (!isspace(*(line + x - 1)) && (x > 1))
  529.         x--;
  530.  
  531.     if (x != 1)
  532.         x++;
  533. }
  534.  
  535. void    newline()
  536. {
  537.     char    l[BUFLEN];
  538.     char   *t = line + x - 1;
  539.     int    inblock = FALSE;
  540.  
  541.         changed = FALSE;
  542.     if (current->text != NULL)
  543.         ptrfree(current->text);
  544.  
  545.     clearline(l, BUFLEN);
  546.     strncpy(l, line, x - 1);
  547.     strcat(l, "\n");
  548.     current->text = strdup(l);
  549. #if 0
  550.     inblock = current->block;
  551. #endif
  552.         assert(current->text);
  553.  
  554.     clreol();
  555.     x = 1;
  556.     y = down1(y);
  557.     gotoxy(x, y + 6);
  558.  
  559.     if (current->next == NULL) {
  560.         if ((current->next = (LINE *) calloc(1, sizeof(LINE))) == NULL)
  561.             return;
  562.         current->next->text = strdup(t);
  563.         current->next->block = inblock;
  564.                 assert(current->next->text);
  565.         current->next->next = NULL;
  566.         current->next->prev = current;
  567.         current = current->next;
  568.                 last = current;
  569.                 assert(current->text);
  570.         putl(current);
  571.                 msgbuf.first = first;
  572.                 msgbuf.last = last;
  573.         clearline(line, BUFLEN);
  574.         if (current->text != NULL)
  575.             strcpy(line, current->text);
  576.         return;
  577.     }
  578.  
  579.     if (strchr(t, '\n') != NULL) {
  580.         LINE   *nl;
  581.         if ((nl = (LINE *) calloc(1, sizeof(LINE))) == NULL)
  582.                                 return;
  583.  
  584.                 nl->text = strdup(t);
  585.         nl->block = inblock;
  586.                 assert(nl->text);
  587.                 nl->next = current->next;
  588.                 nl->next->prev = nl;
  589.                 current->next = nl;
  590.         nl->prev = current;
  591.                 current = nl;
  592.  
  593.                 if ((y + 6) < maxy)
  594.                         scrolldown(1, y + 6, maxx, maxy, 1);
  595.  
  596.                 gotoxy(1, y + 6);
  597.                 clreol();
  598.                 assert(current->text);
  599.         putl(current);
  600.                 msgbuf.first = first;
  601.                 msgbuf.last = last;
  602.         clearline(line, BUFLEN);
  603.         if (current->text != NULL)
  604.             strcpy(line, current->text);
  605.         return;
  606.     }
  607.  
  608.     clearline(l, BUFLEN);
  609.         strcpy(l, t);
  610.         assert(current->next);
  611.     current = current->next;
  612.     if (current->text) {
  613.         strcat(l, current->text);
  614.         ptrfree(current->text);
  615.         current->text = NULL;
  616.     }
  617.  
  618.     clearline(line, BUFLEN);
  619.         x = 0;
  620.         changed = TRUE;
  621.     strcpy(line, l);
  622.     wrapline();
  623. }
  624.  
  625. void    go_pgup()
  626. {
  627.     int    count = y - 1;
  628.     LINE   *l = current;
  629.     /* LINE   *t = current; */
  630.  
  631.         if (changed) {
  632.                 if (current->text != NULL)
  633.                         ptrfree(current->text);
  634.  
  635.                 current->text = strdup(line);
  636.         assert(current->text);
  637.         clearline(line,sizeof(line));
  638.                 changed = FALSE;
  639.     }
  640.  
  641.     while (count-- && current->prev) {
  642.         current = current->prev;
  643.     }
  644.  
  645.     count = maxy - 7;
  646.     while (count-- && current->prev) {
  647.         current = current->prev;
  648.     }
  649.  
  650.     if (l != current) {
  651.         y = 1;
  652.         l = current;
  653.         count = 0;
  654.         clrwnd(1,7,maxx,maxy);
  655.         while (((count + 7) < maxy) && (l->next)) {
  656. #if 0
  657.             if ((l != anchorpt) && (anchorpt != NULL))
  658.                 l->block ^= 1;
  659. #endif
  660.             gotoxy(1,count++ + 7);
  661.             putl(l);
  662.             l = l->next;
  663.         }
  664.         gotoxy(1,count + 7);
  665.         putl(l);
  666.     }
  667.     if (current->text != NULL)
  668.         strcpy(line,current->text);
  669. }
  670.  
  671. void    go_pgdown()
  672. {
  673.     int    count = maxy - 7;
  674.     LINE   *l = current;
  675.  
  676.         if (changed) {
  677.                 if (current->text != NULL)
  678.                         ptrfree(current->text);
  679.  
  680.                 current->text = strdup(line);
  681.                 assert(current->text);
  682.         changed = FALSE;
  683.         clearline(line,sizeof(line));
  684.         }
  685.  
  686.     while (count-- && current->next) {
  687.         current = current->next;
  688.     }
  689.  
  690.     if (l != current) {
  691.         count = 0;
  692.         l = current;
  693.         clrwnd(1,7,maxx,maxy);
  694.         while (((count + 7) < maxy) && l->next) {
  695. #if 0
  696.             if ((l != anchorpt) && (anchorpt != NULL))
  697.                 l->block ^= 1;
  698. #endif
  699.             gotoxy(1,++count + 6);
  700.             putl(l);
  701.             l = l->next;
  702.         }
  703.         gotoxy(1,++count + 6);
  704.         putl(l);
  705.     }
  706.     y = 1;
  707.     if (current->text != NULL)
  708.         strcpy(line,current->text);
  709. }
  710.  
  711. void    delete_line()
  712. {
  713.     LINE   *t = current;
  714.     LINE   *l = current;
  715.     int    y2;
  716.  
  717.     changed = FALSE;
  718.  
  719.     if (current->next == NULL) {
  720.         msgbuf.last = current->prev;    /* deleting last line */
  721.         if (current->text != NULL)
  722.             ptrfree(current->text);
  723.         current->text = NULL;
  724.         gotoxy(x=1,y+6);
  725.         clearline(line,sizeof(line));
  726.         clreol();
  727.         return;
  728.     }
  729.  
  730.         if ((y+6) < maxy)
  731.                 scrollup(1, y + 6, maxx, maxy, 1);
  732.         else
  733.                 scrollup(1,maxy,maxx,maxy,0);
  734.  
  735.         t = current;
  736.  
  737.     clearline(line, BUFLEN);
  738.  
  739.     assert(current);
  740.  
  741.         if (current->next == NULL) {
  742.  
  743.         if (current->text != NULL)
  744.             ptrfree(current->text);
  745.         assert(current);
  746.                 current->text = NULL;
  747.  
  748.                 if (current->prev != NULL) {
  749.                         current = current->prev;
  750.                         ptrfree(current->next);
  751.                         current->next = NULL;
  752.                         y--;
  753.                         if (y < 1) {
  754.                                 y = 1;
  755.                                 clreol();
  756.                         }
  757.  
  758.                         gotoxy(1,y + 6);
  759.             clearline(line,sizeof(line));
  760.             if (current->text != NULL)
  761.                 strcpy(line,current->text);
  762.             putl(current);
  763.             x = min(x,strlen(line));
  764.                 }
  765.                 else {
  766.             first = current;
  767.             x = y = 1;
  768.                 }
  769.  
  770.                 msgbuf.first = first;
  771.                 msgbuf.last = last = current;
  772.                 current->next = NULL;
  773.         return;
  774.     }
  775.  
  776.         assert(current->next);
  777.  
  778.         if (current->prev != NULL) {     /* first line? */
  779.                 current->next->prev = current->prev; /* no */
  780.                 current->prev->next = current->next;
  781.         }
  782.         else {
  783.                 current->next->prev = NULL; /* yes */
  784.                 first = current->next;
  785.         }
  786.  
  787.         current = current->next;
  788.  
  789.         msgbuf.first = first;
  790.         msgbuf.last = last;
  791.  
  792.         if (t->text != NULL)
  793.         ptrfree(t->text);
  794.  
  795.         t->text = NULL;
  796.  
  797.         ptrfree(t);
  798.         t = NULL;
  799.  
  800.     if (current->text != NULL)
  801.         strcpy(line, current->text);
  802.     else
  803.         clearline(line,sizeof(line));
  804.  
  805.         if (x > strlen(line))
  806.         go_eol();
  807.  
  808.     l = current; y2 = y;
  809.     while (((y2 + 6) < maxy) && l->next && l->next->text) {
  810.         y2++;
  811.         l = l->next;
  812.     }
  813.  
  814.     gotoxy(1,y2 + 6);
  815.     putl(l);
  816.     x = max(1,x);
  817. }
  818.  
  819. void    anchor()
  820. {
  821.         if (anchorpt != NULL) {
  822.         set_color(co_normal);
  823.         refresh(current,y=1);
  824.         anchorpt->block = 0;
  825.         anchorpt->column = 0;
  826.         anchorpt = NULL;
  827.         while (pastebuf) {
  828.             ptrfree(pastebuf->text);
  829.             if (pastebuf->next) {
  830.                 pastebuf = pastebuf->next;
  831.                 ptrfree(pastebuf->prev);
  832.             }
  833.             else {
  834.                 ptrfree(pastebuf);
  835.                 pastebuf = NULL;
  836.             }
  837.         }
  838.         }
  839.     anchorpt = current;
  840.     current->column = x;
  841.     current->block = 1;
  842.     gotoxy(1,y+6);
  843.     putl(current);
  844. }
  845.  
  846. void    cut()
  847. {
  848.     LINE *f = current;
  849.     LINE *l = current;
  850.  
  851.     if (changed) {
  852.         if (current->text != NULL)
  853.             ptrfree(current->text);
  854.         current->text = strdup(line);
  855.         assert(current->text);
  856.     }
  857.  
  858.     while (l->next && (l != anchorpt))
  859.         l = l->next;
  860.  
  861.     if (l != anchorpt) {
  862.         l = current;
  863.         while (f->prev && (f != anchorpt))
  864.             f = f->prev;
  865.         if (f != anchorpt)
  866.             return;
  867.     }
  868.  
  869.     if (f->prev == NULL)
  870.         first = l->next;
  871.     else
  872.         f->prev->next = l->next;
  873.  
  874.     if (l->next == NULL)
  875.         last = f->prev;
  876.     else
  877.         l->next->prev = f->prev;
  878.  
  879.     if (l->next != NULL)
  880.         current = l->next;
  881.     else
  882.         current = f->prev;
  883.  
  884.     l->next = NULL;
  885.     f->prev = NULL;
  886.  
  887.     if ((first == NULL) && (last == NULL))
  888.         first = last = current = (LINE *) calloc(1,sizeof(LINE));
  889.  
  890.     pastebuf = f;
  891.  
  892.     clearline(line,sizeof(line));
  893.     if (current->text != NULL)
  894.         strcpy(line,current->text);
  895.  
  896.     refresh(current,1);
  897.     y = x = 1;
  898. }
  899.  
  900. void    paste()
  901. {
  902.     LINE *l = pastebuf;
  903.     LINE *t,*s = NULL;
  904.     LINE *t1 = current->prev;
  905.  
  906.     if (l == NULL)
  907.         return;
  908.  
  909.     if (changed) {
  910.         if (current->text != NULL)
  911.             ptrfree(current->text);
  912.         current->text = strdup(line);
  913.         assert(current->text);
  914.     }
  915.  
  916.     while (l) {
  917.         t = (LINE *) calloc(1,sizeof(LINE));
  918.         if (s == NULL)
  919.             s = t;
  920.         current->prev = t;
  921.         t->next = current;
  922.         t->prev = t1;
  923.         if (t1 == NULL)
  924.             first = t;
  925.         else
  926.             t1->next = t;
  927.         t->text = strdup(l->text);
  928.         l = l->next;
  929.         t1 = t;
  930.     }
  931.  
  932.     current = s;
  933.     if (current->text != NULL)
  934.         strcpy(line,current->text);
  935.  
  936.     refresh(current,1);
  937.     y = x = 1;
  938. }
  939.  
  940.  
  941. static void reformat(LINE *cl)
  942.  
  943. {
  944.     char *t;
  945.     LINE *l = cl->next;
  946.         int y2 = y;
  947.  
  948.         if (cl->next == NULL)
  949.                 return;
  950.  
  951.         while ((cl->next->next != NULL) & (strchr(cl->text,'\n') == NULL)) {
  952.                 t = cl->text;
  953.                 cl->text = cl->next->text;
  954.                 cl->next->next->prev = cl;
  955.                 cl->next = cl->next->next;
  956.         ptrfree(l);
  957.         wrap(cl,t,y2);
  958.                 if (cl->next == NULL)
  959.                         return;
  960.                 cl = cl->next;
  961.                 y2++;
  962.         }
  963. }
  964.  
  965. void    quit()
  966.  
  967. {
  968.     anchorpt = NULL;
  969.     set_color(co_normal);
  970.     shownotes = noteflag;
  971.     if (changed) {
  972.         if (current->text) {
  973.             if ((current->text = realloc(current->text,strlen(line)+1)) == NULL) {
  974.                 gotoxy(9,1);
  975.                 clreol();
  976.                 set_color(co_warn);
  977.                 bputs("*warning* ");
  978.                 bputs("memory error! message truncated, press a key");
  979.                 getkey();
  980.                 set_color(co_normal);
  981.             }
  982.             memset(current->text,0,strlen(line)+1);
  983.             strcpy(current->text, line);
  984.         }
  985.         else {
  986.             current->text = strdup(line);
  987.             assert(current->text);
  988.         }
  989.     }
  990.  
  991.     if (first == NULL)
  992.         first = last = current;
  993.  
  994.     msgbuf.first = first;
  995.     if (last->next != NULL)
  996.         msgbuf.last = last->next;
  997.     else
  998.         msgbuf.last = last;
  999.  
  1000.     done =    SAVE;
  1001. }
  1002.  
  1003.  
  1004. void    die()
  1005.  
  1006. {
  1007.     if (!confirm(confirmations))
  1008.         showheader(message);
  1009.     else
  1010.         done = ABORT;
  1011. }
  1012.  
  1013. void    imptxt()
  1014. {
  1015.     msgbuf.last = last;
  1016.     msgbuf.first = first;
  1017.     if (current->text != NULL)
  1018.         ptrfree(current->text);
  1019.     if (strlen(line) > 0) {
  1020.         current->text = strdup(line);
  1021.         assert(current->text);
  1022.     }
  1023.     else
  1024.         current->text = NULL;
  1025.     import(current);
  1026.     showheader(message);
  1027.     first = msgbuf.first;
  1028.     last = msgbuf.last;
  1029.     refresh(current, 1);
  1030.     x = y = 1;
  1031.     if (current->text != NULL)
  1032.         strcpy(line, current->text);
  1033.     else
  1034.         clearline(line,sizeof(line));
  1035. }
  1036.  
  1037. void    outtext()
  1038.  
  1039. {
  1040.     if (pastebuf != NULL)
  1041.         export(pastebuf);
  1042.     else if (anchorpt != NULL)
  1043.         export(anchorpt);
  1044.     else if (current != NULL)
  1045.         export(current);
  1046. }
  1047.  
  1048.  
  1049. void    shellos()
  1050. {
  1051. #ifndef MINI
  1052.     if (changed) {
  1053.         if (current->text != NULL)
  1054.             ptrfree(current->text);
  1055.         current->text = strdup(line);
  1056.         assert(current->text);
  1057.     }
  1058.     os();
  1059.     showheader(message);
  1060.     x = y = 1;
  1061.     refresh(current, 1);
  1062. #endif
  1063. }
  1064.  
  1065. void    helped()
  1066. {
  1067.     if (changed) {
  1068.         if (current->text != NULL)
  1069.             ptrfree(current->text);
  1070.         current->text = strdup(line);
  1071.         assert(current->text);
  1072.     }
  1073.     helpedit();
  1074.     showheader(message);
  1075.     x = y = 1;
  1076.     refresh(current, 1);
  1077. } /* helped */
  1078.  
  1079. void    format()
  1080.  
  1081. {
  1082.     if (changed) {
  1083.         if (current->text)
  1084.             ptrfree(current->text);
  1085.         current->text = strdup(line);
  1086.         assert(current->text);
  1087.     }
  1088.     reformat(current);
  1089.     clearline(line,BUFLEN);
  1090.     if (current->text)
  1091.         strcpy(line,current->text);
  1092.     x = 1;
  1093. }
  1094.  
  1095. void    toggle_ins()
  1096.  
  1097. {
  1098.     insert = !insert;
  1099.     if (insert) {
  1100.         set_color(co_info);
  1101.         gotoxy((maxx - 4), 5);
  1102.         bputs("ins");
  1103.     }
  1104.     else {
  1105.         gotoxy((maxx - 4), 5);
  1106.         bputs("   ");
  1107.     }
  1108.     set_color(co_normal);
  1109. }
  1110.  
  1111. void    tabit()
  1112.  
  1113. {
  1114.     changed = TRUE;
  1115.     if (!(x%tabsize))
  1116.         insert_char(' ');
  1117.         
  1118.     while (x % tabsize)
  1119.         insert_char(' ');
  1120.         
  1121.     insert_char(' ');
  1122. }
  1123.  
  1124. void    go_tos()
  1125.  
  1126. {
  1127.     int    count = y - 1;
  1128.  
  1129.         if (changed) {
  1130.                 if (current->text != NULL)
  1131.                         ptrfree(current->text);
  1132.  
  1133.                 current->text = strdup(line);
  1134.                 assert(current->text);
  1135.                 changed = FALSE;
  1136.     }
  1137.  
  1138.     while (count-- && current->prev) {
  1139.         current = current->prev;
  1140.     }
  1141.     x = y = 1;
  1142.     clearline(line,sizeof(line));
  1143.     if (current->text != NULL)
  1144.         strcpy(line,current->text);
  1145. }
  1146.  
  1147. void    go_bos()
  1148.  
  1149. {
  1150.         if (changed) {
  1151.                 if (current->text != NULL)
  1152.                         ptrfree(current->text);
  1153.  
  1154.                 current->text = strdup(line);
  1155.                 assert(current->text);
  1156.                 changed = FALSE;
  1157.     }
  1158.  
  1159.     while (((y + 6) < maxy) && current->next) {
  1160.         current = current->next;
  1161.         y++;
  1162.     }
  1163.     x = 1;
  1164.     clearline(line,sizeof(line));
  1165.     if (current->text != NULL)
  1166.         strcpy(line,current->text);
  1167. }
  1168.  
  1169. void go_tom()
  1170.  
  1171. {
  1172.         if (changed) {
  1173.                 if (current->text != NULL)
  1174.                         ptrfree(current->text);
  1175.  
  1176.                 current->text = strdup(line);
  1177.                 assert(current->text);
  1178.                 changed = FALSE;
  1179.     }
  1180.  
  1181.     current = first;
  1182.     clearline(line,sizeof(line));
  1183.     if (current->text != NULL)
  1184.         strcpy(line,current->text);
  1185.     refresh(current,1);
  1186.     x = y = 1;
  1187. }
  1188.  
  1189. void go_bom()
  1190.  
  1191. {
  1192.         if (changed) {
  1193.                 if (current->text != NULL)
  1194.                         ptrfree(current->text);
  1195.  
  1196.                 current->text = strdup(line);
  1197.                 assert(current->text);
  1198.                 changed = FALSE;
  1199.     }
  1200.  
  1201.     current = last;
  1202.     x = y = 1;
  1203.  
  1204.     clearline(line,sizeof(line));
  1205.     if (current->text != NULL)
  1206.         strcpy(line,current->text);
  1207.     if (current->prev) {
  1208.         refresh(current->prev,1);
  1209.         y = 2;
  1210.     }
  1211.     else
  1212.         refresh(current,1);
  1213. }
  1214.  
  1215. void killeol()
  1216.  
  1217. {
  1218.     char *s;
  1219.  
  1220.     if (strchr(line,'\n') == NULL)
  1221.         *(s = (line + x - 1)) = '\0';
  1222.     else {
  1223.         *(line + x - 1) = '\n';
  1224.         *(s = (line + x)) = '\0';
  1225.     }
  1226.     memset(s,0,sizeof line - (int)(s - line) - 1);
  1227.     changed = TRUE;
  1228.     clreol();
  1229. }
  1230.  
  1231. int     editmsg()
  1232. {
  1233.     unsigned int     ch;
  1234.  
  1235. #ifdef EXTERNEDIT
  1236.     if (!writebuffile("$msgedq.tmp", &msgbuf))
  1237.       return ABORT;
  1238.     if (!shell("LS.COM", "$msgedq.tmp"))
  1239.       return ABORT;
  1240.     if (readbuffile("$msgedq.tmp", &msgbuf))
  1241.       return SAVE;
  1242.     else
  1243.       return ABORT;
  1244. #endif
  1245.  
  1246.     noteflag = shownotes;
  1247.         anchorpt = NULL;
  1248.     shownotes = TRUE;
  1249.     x = y = 1;
  1250.         current = first = msgbuf.first;
  1251.     last = msgbuf.last;
  1252.     clearline(line, BUFLEN);
  1253.  
  1254.     if (insert) {
  1255.         set_color(co_info);
  1256.         gotoxy((maxx-4), 5);
  1257.         bputs("ins");
  1258.         set_color(co_normal);
  1259.     }
  1260.  
  1261.     if (first == NULL) {
  1262.         if ((first = (LINE *) calloc(1, sizeof(LINE))) == NULL) {
  1263.             gotoxy(9,1);
  1264.             clreol();
  1265.             set_color(co_warn);
  1266.             bputs("*warning* ");
  1267.             bputs("ran out of memory!  press a key");
  1268.             getkey();
  1269.             set_color(co_normal);
  1270.             return(ABORT);
  1271.         }
  1272.  
  1273.         first->text = NULL;
  1274.         first->prev = NULL;
  1275.         last = current = first;
  1276.     }
  1277.     else if (current->text != NULL)
  1278.         strcpy(line, current->text);
  1279.     else
  1280.         clearline(line,sizeof(line));
  1281.  
  1282.     refresh(current, 1);
  1283.     gotoxy(1, 7);
  1284.     done = FALSE;
  1285.  
  1286.     while (!done) {
  1287.         gotoxy(x,y+6);
  1288.         video_update();
  1289.         ch = getkey();
  1290.         if (ch & 0xff) {
  1291.             if (editckeys[(ch & 0xff)] == NULL) {
  1292.                                 changed = TRUE;
  1293.                 if (insert) 
  1294.                     insert_char((char) (ch & 0xff));
  1295.                 else {
  1296.                     delete_character();
  1297.                     insert_char((char) (ch & 0xff));
  1298.                 }
  1299.             }
  1300.             else
  1301.                 editckeys[(ch & 0xff)]();
  1302.         }
  1303.         else if (editakeys[(ch >> 8)] != NULL)
  1304.             editakeys[(ch >> 8)]();
  1305.         else
  1306.             continue;
  1307.     }
  1308.  
  1309.     shownotes = noteflag;
  1310.     return(done);
  1311. }
  1312.